{
  ProcessRoutines
  todo
}

unit ProcessRoutines;

interface

  uses
    Windows;

  //****************************************************************************
  //* Process record
  //****************************************************************************
  type
    TProcessInfo = record
      Success   : Boolean;
      StartInfo : TStartupInfo;
      ProcInfo  : TProcessInformation;
    end;
    PProcessInfo = ^TProcessInfo;

  function RunCommand(CommandLine : WideString; Hide : Boolean; RProcessInfo : PProcessInfo) : Boolean;
  function GetWindowHandle(PID : Cardinal) : HWND;
  function HandleEnum(Handle : HWND; lParam : LPARAM) : Boolean; stdcall;

implementation

  type
    TProcessToHandle = record
      HandleBuffer  : HWND;
      TargetProcess : Cardinal;
    end;

  //****************************************************************************
  //* Routines
  //****************************************************************************
  function RunCommand(CommandLine : WideString; Hide : Boolean; RProcessInfo : PProcessInfo) : Boolean;
  var
    {StartInfo : TStartupInfo;
    ProcInfo : TProcessInformation;}
    ProcessInfo : TProcessInfo;
    Command : WideString;
  begin
    Command := CommandLine;
    UniqueString(Command);
    //Create process
    ZeroMemory(@ProcessInfo.StartInfo, SizeOf(TStartupInfo));
    ProcessInfo.StartInfo.cb := SizeOf(TStartupInfo);
    if Hide = true then
    begin
      ProcessInfo.StartInfo.dwFlags := STARTF_USESHOWWINDOW;
      ProcessInfo.StartInfo.wShowWindow := SW_HIDE;
    end;
    ProcessInfo.Success := CreateProcess(
      nil, PChar(Command), nil, nil, True, 0, nil, nil, ProcessInfo.StartInfo,
      ProcessInfo.ProcInfo
    );
    //Attempt to hide again
    if Hide = true then ShowWindow(GetWindowHandle(ProcessInfo.ProcInfo.dwProcessId), SW_HIDE);
    //Return stuff
    if RProcessInfo <> nil then RProcessInfo^ := ProcessInfo; //Process info record
    Result := ProcessInfo.Success; //Command worked?
  end;

  function GetWindowHandle(PID : Cardinal) : HWND;
  var
    ProcessToHandle : TProcessToHandle;
  begin
    Result := 0;
    ProcessToHandle.TargetProcess := PID;
    if EnumWindows(@HandleEnum, Integer(@ProcessToHandle)) then
      //showmessage(format('%d', [ProcessToHandle.HandleBuffer]));
      Result := ProcessToHandle.HandleBuffer
  end;

  function HandleEnum(Handle : HWND; lParam : LPARAM) : Boolean; stdcall;
  var
    PProcessToHandle : ^TProcessToHandle;
  begin
    Result := true;
    PProcessToHandle := Pointer(lParam);
    if GetWindowThreadProcessId(Handle) = PProcessToHandle^.TargetProcess then
    begin
      PProcessToHandle^.HandleBuffer := Handle;
      Result := false;
    end;
  end;

end.
